home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Programming / SWI / source / src / pl-fli.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-18  |  38.0 KB  |  2,156 lines

  1. /*  $Id: pl-fli.c,v 1.27 1998/02/18 13:56:52 jan Exp $
  2.  
  3.     Copyright (c) 1990 Jan Wielemaker. All rights reserved.
  4.     See ../LICENCE to find out about your rights.
  5.     jan@swi.psy.uva.nl
  6.  
  7.     Purpose: Virtual machine instruction interpreter
  8. */
  9.  
  10. /*#define O_SECURE 1*/
  11. /*#define O_DEBUG 1*/
  12. #include "pl-incl.h"
  13.  
  14. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  15. SWI-Prolog  new-style  foreign-language  interface.   This  new  foreign
  16. interface is a mix of the old  interface using the ideas on term-handles
  17. from  Quintus  Prolog.  Term-handles  are    integers  (unsigned  long),
  18. describing the offset of the term-location relative   to the base of the
  19. local stack.
  20.  
  21. If a C-function has to  store  intermediate   results,  it  can do so by
  22. creating a new term-reference using   PL_new_term_ref().  This functions
  23. allocates a cell on the local stack and returns the offset.
  24.  
  25. While a foreign function is on top of  the stack, the local stacks looks
  26. like this:
  27.  
  28.                               | <-- lTop
  29.     -----------------------------------------------
  30.     | Allocated term-refs using PL_new_term_ref() |
  31.     -----------------------------------------------
  32.     | reserved for #term-refs (1)              |
  33.     -----------------------------------------------
  34.     | foreign-function arguments (term-refs)      |
  35.     -----------------------------------------------
  36.     | Local frame of foreign function             |
  37.     -----------------------------------------------
  38.  
  39. On a call-back to Prolog using  PL_call(),  etc., (1) is filled with the
  40. number of term-refs allocated. This  information   (stored  as  a tagged
  41. Prolog int) is used by the garbage collector to update the stack frames.
  42. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  43.  
  44. #if O_SECURE
  45. #define setHandle(h, w)        { assert(*valTermRef(h) != QID_MAGIC); \
  46.                   (*valTermRef(h) = (w)); \
  47.                 }
  48. #else
  49. #define setHandle(h, w)        (*valTermRef(h) = (w))
  50. #endif
  51. #define valHandleP(h)        valTermRef(h)
  52.  
  53. #undef ulong
  54. #define ulong unsigned long
  55.  
  56. static inline word
  57. valHandle(term_t r)
  58. { Word p = valTermRef(r);
  59.  
  60.   deRef(p);
  61.   return *p;
  62. }
  63.  
  64.  
  65.          /*******************************
  66.          *       CREATE/RESET        *
  67.          *******************************/
  68.  
  69. #undef PL_new_term_refs
  70. #undef PL_new_term_ref
  71. #undef PL_reset_term_refs
  72.  
  73. term_t
  74. PL_new_term_refs(int n)
  75. { Word t = (Word)lTop;
  76.   term_t r = consTermRef(t);
  77.  
  78.   lTop = (LocalFrame)(t+n);
  79.   verifyStack(local);
  80.  
  81.   while(n-- > 0)
  82.   { SECURE(assert(*t != QID_MAGIC));
  83.     setVar(*t++);
  84.   }
  85.   
  86.   return r;
  87. }
  88.  
  89.  
  90. term_t
  91. PL_new_term_ref()
  92. { Word t = (Word)lTop;
  93.   term_t r = consTermRef(t);
  94.  
  95.   lTop = (LocalFrame)(t+1);
  96.   verifyStack(local);
  97.   SECURE(assert(*t != QID_MAGIC));
  98.   setVar(*t);
  99.   
  100.   return r;
  101. }
  102.  
  103.  
  104. void
  105. PL_reset_term_refs(term_t r)
  106. { lTop = (LocalFrame) valTermRef(r);
  107. }
  108.  
  109.  
  110. term_t
  111. PL_copy_term_ref(term_t from)
  112. { Word t   = (Word)lTop;
  113.   term_t r = consTermRef(t);
  114.   Word p2  = valHandleP(from);
  115.  
  116.   lTop = (LocalFrame)(t+1);
  117.   verifyStack(local);
  118.   deRef(p2);
  119.   *t = isVar(*p2) ? makeRef(p2) : *p2;
  120.   
  121.   return r;
  122. }
  123.  
  124.  
  125.          /*******************************
  126.          *           ATOMS        *
  127.          *******************************/
  128.  
  129. atom_t
  130. PL_new_atom(const char *s)
  131. { return (atom_t) lookupAtom((char *)s); /* hack */
  132. }
  133.  
  134.  
  135. const char *
  136. PL_atom_chars(atom_t a)
  137. { return (const char *) stringAtom(a);
  138. }
  139.  
  140.  
  141. functor_t
  142. PL_new_functor(atom_t f,  int a)
  143. { return lookupFunctorDef(f, a);
  144. }
  145.  
  146.  
  147. atom_t
  148. PL_functor_name(functor_t f)
  149. { return nameFunctor(f);
  150. }
  151.  
  152.  
  153. int
  154. PL_functor_arity(functor_t f)
  155. { return arityFunctor(f);
  156. }
  157.  
  158.  
  159.          /*******************************
  160.          *    QUINTUS WRAPPER SUPPORT   *
  161.          *******************************/
  162.  
  163. bool
  164. PL_cvt_i_integer(term_t p, long *c)
  165. { return PL_get_long(p, c);
  166. }
  167.  
  168.  
  169. bool
  170. PL_cvt_i_float(term_t p, double *c)
  171. { return PL_get_float(p, c);
  172. }
  173.  
  174.  
  175. bool
  176. PL_cvt_i_single(term_t p, float *c)
  177. { double f;
  178.  
  179.   if ( PL_get_float(p, &f) )
  180.   { *c = (float)f;
  181.     succeed;
  182.   }
  183.  
  184.   fail;
  185. }
  186.  
  187.  
  188. bool
  189. PL_cvt_i_string(term_t p, char **c)
  190. { return PL_get_chars(p, c, CVT_ATOM|CVT_STRING);
  191. }
  192.  
  193.  
  194. bool
  195. PL_cvt_i_atom(term_t p, atom_t *c)
  196. { return PL_get_atom(p, c);
  197. }
  198.  
  199.  
  200. bool
  201. PL_cvt_o_integer(long c, term_t p)
  202. { return PL_unify_integer(p, c);
  203. }
  204.  
  205.  
  206. bool
  207. PL_cvt_o_float(double c, term_t p)
  208. { return PL_unify_float(p, c);
  209. }
  210.  
  211.  
  212. bool
  213. PL_cvt_o_single(float c, term_t p)
  214. { return PL_unify_float(p, c);
  215. }
  216.  
  217.  
  218. bool
  219. PL_cvt_o_string(const char *c, term_t p)
  220. { return PL_unify_atom_chars(p, c);
  221. }
  222.  
  223.  
  224. bool
  225. PL_cvt_o_atom(atom_t c, term_t p)
  226. { return PL_unify_atom(p, c);
  227. }
  228.  
  229.  
  230.          /*******************************
  231.          *          COMPARE        *
  232.          *******************************/
  233.  
  234. int
  235. PL_compare(term_t t1, term_t t2)
  236. { Word p1 = valHandleP(t1);
  237.   Word p2 = valHandleP(t2);
  238.  
  239.   return compareStandard(p1, p2);    /* -1, 0, 1 */
  240. }
  241.  
  242.  
  243.          /*******************************
  244.          *          INTEGERS        *
  245.          *******************************/
  246.  
  247. word
  248. makeNum(long i)
  249. { if ( inTaggedNumRange(i) )
  250.     return consInt(i);
  251.  
  252.   return globalLong(i);
  253. }
  254.  
  255.  
  256.          /*******************************
  257.          *           CONS-*        *
  258.          *******************************/
  259.  
  260. void
  261. PL_cons_functor(term_t h, functor_t fd, ...)
  262. { int arity = arityFunctor(fd);
  263.  
  264.   if ( arity == 0 )
  265.   { setHandle(h, nameFunctor(fd));
  266.   } else
  267.   { Word a = allocGlobal(1 + arity);
  268.     va_list args;
  269.  
  270.     va_start(args, fd);
  271.     setHandle(h, consPtr(a, TAG_COMPOUND|STG_GLOBAL));
  272.     *a++ = fd;
  273.     while(arity-- > 0)
  274.     { term_t r = va_arg(args, term_t);
  275.       Word p = valHandleP(r);
  276.  
  277.       deRef(p);
  278.       *a++ = (isVar(*p) ? makeRef(p) : *p);
  279.     }
  280.     va_end(args);
  281.   }
  282. }
  283.  
  284.  
  285. void
  286. PL_cons_list(term_t l, term_t head, term_t tail)
  287. { Word a = allocGlobal(3);
  288.   Word p;
  289.   
  290.   a[0] = FUNCTOR_dot2;
  291.   p = valHandleP(head);
  292.   deRef(p);
  293.   a[1] = (isVar(*p) ? makeRef(p) : *p);
  294.   p = valHandleP(tail);
  295.   deRef(p);
  296.   a[2] = (isVar(*p) ? makeRef(p) : *p);
  297.  
  298.   setHandle(l, consPtr(a, TAG_COMPOUND|STG_GLOBAL));
  299. }
  300.  
  301.          /*******************************
  302.          *     POINTER <-> PROLOG INT    *
  303.          *******************************/
  304.  
  305. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  306. Pointers are not a special type in Prolog. Instead, they are represented
  307. by an integer. The funtions below convert   integers  such that they can
  308. normally be expressed as a tagged  integer: the heap_base is subtracted,
  309. it is divided by 4 and the low 2   bits  are placed at the top (they are
  310. normally 0). longToPointer() does the inverse operation.
  311. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  312.  
  313. static ulong
  314. pointerToLong(void *ptr)
  315. { ulong p = (ulong) ptr;
  316.   ulong low = p & 0x3L;
  317.  
  318.   p -= heap_base;
  319.   p >>= 2;
  320.   p |= low<<(sizeof(ulong)*8-2);
  321.   
  322.   return p;
  323. }
  324.  
  325.  
  326. static void *
  327. longToPointer(ulong p)
  328. { ulong low = p >> (sizeof(ulong)*8-2);
  329.  
  330.   p <<= 2;
  331.   p |= low;
  332.   p += heap_base;
  333.  
  334.   return (void *) p;
  335. }
  336.  
  337.  
  338.          /*******************************
  339.          *          GET-*        *
  340.          *******************************/
  341.  
  342. int
  343. PL_get_atom(term_t t, atom_t *a)
  344. { word w = valHandle(t);
  345.  
  346.   if ( isAtom(w) )
  347.   { *a = (atom_t) w;
  348.     succeed;
  349.   }
  350.   fail;
  351. }
  352.  
  353.  
  354. int
  355. PL_get_atom_chars(term_t t, char **s)
  356. { word w = valHandle(t);
  357.  
  358.   if ( isAtom(w) )
  359.   { *s = stringAtom(w);
  360.     succeed;
  361.   }
  362.   fail;
  363. }
  364.  
  365. #ifdef O_STRING
  366. int
  367. PL_get_string(term_t t, char **s, int *len)
  368. { word w = valHandle(t);
  369.  
  370.   if ( isString(w) )
  371.   { *s = valString(w);
  372.     *len = sizeString(w);
  373.     succeed;
  374.   }
  375.   fail;
  376. }
  377. #endif
  378.  
  379. #define discardable_buffer     (LD->fli._discardable_buffer)
  380. #define buffer_ring        (LD->fli._buffer_ring)
  381. #define current_buffer_id    (LD->fli._current_buffer_id)
  382.  
  383. static Buffer
  384. findBuffer(int flags)
  385. { Buffer b;
  386.  
  387.   if ( flags & BUF_RING )
  388.   { if ( ++current_buffer_id == BUFFER_RING_SIZE )
  389.       current_buffer_id = 0;
  390.     b = &buffer_ring[current_buffer_id];
  391.   } else
  392.     b = &discardable_buffer;
  393.  
  394.   if ( !b->base )
  395.     initBuffer(b);
  396.  
  397.   emptyBuffer(b);
  398.   return b;
  399. }
  400.  
  401.  
  402. char *
  403. buffer_string(const char *s, int flags)
  404. { Buffer b = findBuffer(flags);
  405.   int l = strlen(s) + 1;
  406.  
  407.   addMultipleBuffer(b, s, l, char);
  408.  
  409.   return baseBuffer(b, char);
  410. }
  411.  
  412.  
  413. static int
  414. unfindBuffer(int flags)
  415. { if ( flags & BUF_RING )
  416.   { if ( --current_buffer_id <= 0 )
  417.       current_buffer_id = BUFFER_RING_SIZE-1;
  418.   }
  419.  
  420.   fail;
  421. }
  422.  
  423.  
  424. static char *
  425. malloc_string(const char *s)
  426. { char *c;
  427.   int len = strlen(s)+1;
  428.  
  429.   if ( (c = malloc(len)) )
  430.   { memcpy(c, s, len);
  431.     return c;
  432.   }
  433.  
  434.   outOfCore();
  435.   return NULL;
  436. }
  437.  
  438.  
  439. int
  440. PL_get_list_chars(term_t l, char **s, unsigned flags)
  441. { Buffer b = findBuffer(flags);
  442.   word list = valHandle(l);
  443.   Word arg, tail;
  444.   int c;
  445.   char *r;
  446.  
  447.   while( isList(list) && !isNil(list) )
  448.   { arg = argTermP(list, 0);
  449.     deRef(arg);
  450.     if ( isTaggedInt(*arg) && (c=(int)valInt(*arg)) > 0 && c < 256)
  451.     { addBuffer(b, c, char);
  452.       tail = argTermP(list, 1);
  453.       deRef(tail);
  454.       list = *tail;
  455.       continue;
  456.     }
  457.     return unfindBuffer(flags);
  458.   }
  459.   if (!isNil(list))
  460.     return unfindBuffer(flags);
  461.  
  462.   addBuffer(b, EOS, char);
  463.   r = baseBuffer(b, char);
  464.  
  465.   if ( flags & BUF_MALLOC )
  466.     *s = malloc_string(r);
  467.   else
  468.     *s = r;
  469.  
  470.   succeed;
  471. }
  472.  
  473.  
  474. int
  475. PL_get_chars(term_t l, char **s, unsigned flags)
  476. { word w = valHandle(l);
  477.   char tmp[24];
  478.   char *r;
  479.   int type;
  480.  
  481.   if ( (flags & CVT_ATOM) && isAtom(w) )
  482.   { type = PL_ATOM;
  483.     r = stringAtom(w);
  484.   } else if ( (flags & CVT_INTEGER) && isInteger(w) )
  485.   { type = PL_INTEGER;
  486.     Ssprintf(tmp, "%ld", valInteger(w) );
  487.     r = tmp;
  488.   } else if ( (flags & CVT_FLOAT) && isReal(w) )
  489.   { type = PL_FLOAT;
  490.     Ssprintf(tmp, "%f", valReal(w) );
  491.     r = tmp;
  492. #ifdef O_STRING
  493.   } else if ( (flags & CVT_STRING) && isString(w) )
  494.   { type = PL_STRING;
  495.     r = valString(w);
  496. #endif
  497.   } else if ( (flags & CVT_LIST) )
  498.   { return PL_get_list_chars(l, s, flags);
  499.   } else if ( (flags & CVT_VARIABLE) )
  500.   { type = PL_VARIABLE;
  501.     r = varName(l, tmp);
  502.   } else
  503.     fail;
  504.     
  505.   if ( flags & BUF_MALLOC )
  506.   { *s = malloc_string(r);
  507.   } else if ( ((flags & BUF_RING) && type != PL_ATOM) || /* never atoms */
  508.           (type == PL_STRING) ||    /* always buffer strings */
  509.           r == tmp )        /* always buffer tmp */
  510.   { Buffer b = findBuffer(flags);
  511.     int l = strlen(r) + 1;
  512.  
  513.     addMultipleBuffer(b, r, l, char);
  514.     *s = baseBuffer(b, char);
  515.   } else
  516.     *s = r;
  517.  
  518.   succeed;
  519. }
  520.  
  521.  
  522. int
  523. PL_get_integer(term_t t, int *i)
  524. { word w = valHandle(t);
  525.   
  526.   if ( isTaggedInt(w) )
  527.   { *i = valInt(w);
  528.     succeed;
  529.   }
  530.   if ( isBignum(w) )
  531.   { *i = valBignum(w);
  532.     succeed;
  533.   }
  534.   if ( isReal(w) )
  535.   { real f = valReal(w);
  536.     long l;
  537.  
  538. #ifdef DOUBLE_TO_LONG_CAST_RAISES_SIGFPE
  539.     if ( !((f >= PLMININT) && (f <= PLMAXINT)) )
  540.       fail;
  541. #endif
  542.  
  543.     l = (long)f;
  544.     if ( (real)l == f )
  545.     { *i = l;
  546.       succeed;
  547.     }
  548.   }
  549.   fail;
  550.  
  551.  
  552. int
  553. PL_get_long(term_t t, long *i)
  554. { word w = valHandle(t);
  555.   
  556.   if ( isTaggedInt(w) )
  557.   { *i = valInt(w);
  558.     succeed;
  559.   }
  560.   if ( isBignum(w) )
  561.   { *i = valBignum(w);
  562.     succeed;
  563.   }
  564.   if ( isReal(w) )
  565.   { real f = valReal(w);
  566.     long l;
  567.     
  568. #ifdef DOUBLE_TO_LONG_CAST_RAISES_SIGFPE
  569.     if ( !((f >= PLMININT) && (f <= PLMAXINT)) )
  570.       fail;
  571. #endif
  572.  
  573.     l = (long) f;
  574.     if ( (real)l == f )
  575.     { *i = l;
  576.       succeed;
  577.     }
  578.   }
  579.   fail;
  580.  
  581.  
  582. int
  583. PL_get_float(term_t t, double *f)
  584. { word w = valHandle(t);
  585.   
  586.   if ( isReal(w) )
  587.   { *f = valReal(w);
  588.     succeed;
  589.   }
  590.   if ( isTaggedInt(w) )
  591.   { *f = (double) valInt(w);
  592.     succeed;
  593.   }
  594.   if ( isBignum(w) )
  595.   { *f = (double) valBignum(w);
  596.     succeed;
  597.   }
  598.   fail;
  599. }
  600.  
  601.  
  602. int
  603. PL_get_pointer(term_t t, void **ptr)
  604. { long p;
  605.  
  606.   if ( PL_get_long(t, &p) )
  607.   { *ptr = longToPointer((ulong)p);
  608.  
  609.     succeed;
  610.   }
  611.  
  612.   fail;
  613.  
  614.  
  615.  
  616. int
  617. PL_get_name_arity(term_t t, atom_t *name, int *arity)
  618. { word w = valHandle(t);
  619.  
  620.   if ( isTerm(w) )
  621.   { FunctorDef fd = valueFunctor(functorTerm(w));
  622.  
  623.     *name =  fd->name;
  624.     *arity = fd->arity;
  625.     succeed;
  626.   }
  627.   if ( isAtom(w) )
  628.   { *name = (atom_t)w;
  629.     *arity = 0;
  630.     succeed;
  631.   }
  632.  
  633.   fail;
  634. }
  635.  
  636.  
  637. int
  638. _PL_get_name_arity(term_t t, atom_t *name, int *arity)
  639. { word w = valHandle(t);
  640.  
  641.   if ( isTerm(w) )
  642.   { FunctorDef fd = valueFunctor(functorTerm(w));
  643.  
  644.     *name =  fd->name;
  645.     *arity = fd->arity;
  646.     succeed;
  647.   }
  648.  
  649.   fail;
  650. }
  651.  
  652.  
  653. int
  654. PL_get_functor(term_t t, functor_t *f)
  655. { word w = valHandle(t);
  656.  
  657.   if ( isTerm(w) )
  658.   { *f = functorTerm(w);
  659.     succeed;
  660.   }
  661.   if ( isAtom(w) )
  662.   { *f = lookupFunctorDef(w, 0);
  663.     succeed;
  664.   }
  665.  
  666.   fail;
  667. }
  668.  
  669.  
  670. int
  671. PL_get_module(term_t t, module_t *m)
  672. { atom_t a;
  673.  
  674.   if ( PL_get_atom(t, &a) )
  675.   { *m = lookupModule(a);
  676.     succeed;
  677.   }
  678.  
  679.   fail;
  680. }
  681.  
  682.  
  683. void
  684. _PL_get_arg(int index, term_t t, term_t a)
  685. { word w = valHandle(t);
  686.   Functor f = (Functor)valPtr(w);
  687.   Word p = &f->arguments[index-1];
  688.  
  689.   deRef(p);
  690.  
  691.   if ( isVar(*p) )
  692.     w = consPtr(p, TAG_REFERENCE|storage(w)); /* makeRef() */
  693.   else
  694.     w = *p;
  695.  
  696.   setHandle(a, w);
  697. }
  698.  
  699.  
  700. int
  701. PL_get_arg(int index, term_t t, term_t a)
  702. { word w = valHandle(t);
  703.  
  704.   if ( isTerm(w) && index > 0 )
  705.   { Functor f = (Functor)valPtr(w);
  706.     int arity = arityFunctor(f->definition);
  707.  
  708.     if ( --index < arity )
  709.     { Word p = &f->arguments[index];
  710.  
  711.       deRef(p);
  712.  
  713.       if ( isVar(*p) )
  714.     w = makeRef(p);
  715.       else
  716.     w = *p;
  717.  
  718.       setHandle(a, w);
  719.       succeed;
  720.     }
  721.   }
  722.  
  723.   fail;
  724. }
  725.  
  726.  
  727. int
  728. PL_get_list(term_t l, term_t h, term_t t)
  729. { word w = valHandle(l);
  730.  
  731.   if ( isList(w) )
  732.   { Word p1, p2;
  733.     
  734.     p1 = argTermP(w, 0);
  735.     p2 = argTermP(w, 1);
  736.     deRef(p1);
  737.     deRef(p2);
  738.     setHandle(h, isVar(*p1) ? makeRef(p1) : *p1);
  739.     setHandle(t, isVar(*p2) ? makeRef(p2) : *p2);
  740.     succeed;
  741.   }
  742.   fail;
  743. }
  744.  
  745.  
  746. int
  747. PL_get_head(term_t l, term_t h)
  748. { word w = valHandle(l);
  749.  
  750.   if ( isList(w) )
  751.   { Word p;
  752.     
  753.     p = argTermP(w, 0);
  754.     deRef(p);
  755.     setHandle(h, *p ? *p : makeRef(p));
  756.     succeed;
  757.   }
  758.   fail;
  759. }
  760.  
  761.  
  762. int
  763. PL_get_tail(term_t l, term_t t)
  764. { word w = valHandle(l);
  765.  
  766.   if ( isList(w) )
  767.   { Word p;
  768.     
  769.     p = argTermP(w, 1);
  770.     deRef(p);
  771.     setHandle(t, *p ? *p : makeRef(p));
  772.     succeed;
  773.   }
  774.   fail;
  775. }
  776.  
  777.  
  778. int
  779. PL_get_nil(term_t l)
  780. { word w = valHandle(l);
  781.  
  782.   if ( isNil(w) )
  783.     succeed;
  784.  
  785.   fail;
  786. }
  787.  
  788.  
  789. int
  790. _PL_get_xpce_reference(term_t t, xpceref_t *ref)
  791. { word w = valHandle(t);
  792.  
  793.   if ( hasFunctor(w, FUNCTOR_xpceref1) )
  794.   { Word p = argTermP(w, 0);
  795.  
  796.     do
  797.     { if ( isTaggedInt(*p) )
  798.       { ref->type    = PL_INTEGER;
  799.     ref->value.i = valInt(*p);
  800.  
  801.     succeed;
  802.       } 
  803.       if ( isAtom(*p) )
  804.       { ref->type    = PL_ATOM;
  805.     ref->value.a = (atom_t) *p;
  806.  
  807.     succeed;
  808.       }
  809.       if ( isBignum(*p) )
  810.       { ref->type    = PL_INTEGER;
  811.     ref->value.i = valBignum(*p);
  812.  
  813.     succeed;
  814.       }
  815.     } while(isRef(*p) && (p = unRef(*p)));
  816.  
  817.     return -1;                /* error! */
  818.   }
  819.  
  820.   fail;
  821. }
  822.  
  823.  
  824.          /*******************************
  825.          *        IS-*        *
  826.          *******************************/
  827.  
  828. int
  829. PL_is_variable(term_t t)
  830. { word w = valHandle(t);
  831.  
  832.   return isVar(w) ? TRUE : FALSE;
  833. }
  834.  
  835.  
  836. int
  837. PL_is_atom(term_t t)
  838. { word w = valHandle(t);
  839.  
  840.   return isAtom(w) ? TRUE : FALSE;
  841. }
  842.  
  843.  
  844. int
  845. PL_is_integer(term_t t)
  846. { word w = valHandle(t);
  847.  
  848.   return isInteger(w) ? TRUE : FALSE;
  849. }
  850.  
  851.  
  852. int
  853. PL_is_float(term_t t)
  854. { word w = valHandle(t);
  855.  
  856.   return isReal(w) ? TRUE : FALSE;
  857. }
  858.  
  859.  
  860. int
  861. PL_is_compound(term_t t)
  862. { word w = valHandle(t);
  863.  
  864.   return isTerm(w) ? TRUE : FALSE;
  865. }
  866.  
  867.  
  868. int
  869. PL_is_functor(term_t t, functor_t f)
  870. { word w = valHandle(t);
  871.  
  872.   if ( hasFunctor(w, f) )
  873.     succeed;
  874.  
  875.   fail;
  876. }
  877.  
  878.  
  879. int
  880. PL_is_list(term_t t)
  881. { word w = valHandle(t);
  882.  
  883.   return (isList(w) || isNil(w)) ? TRUE : FALSE;
  884. }
  885.  
  886.  
  887. int
  888. PL_is_atomic(term_t t)
  889. { word w = valHandle(t);
  890.  
  891.   return isAtomic(w) ? TRUE : FALSE;
  892. }
  893.  
  894.  
  895. int
  896. PL_is_number(term_t t)
  897. { word w = valHandle(t);
  898.  
  899.   return isNumber(w) ? TRUE : FALSE;
  900. }
  901.  
  902.  
  903. #ifdef O_STRING
  904. int
  905. PL_is_string(term_t t)
  906. { word w = valHandle(t);
  907.  
  908.   return isString(w) ? TRUE : FALSE;
  909. }
  910.  
  911. int
  912. PL_unify_string_chars(term_t t, const char *s)
  913. { word str = globalString((char *)s);
  914.   Word p = valHandleP(t);
  915.  
  916.   return unifyAtomic(p, str);
  917. }
  918.  
  919. int
  920. PL_unify_string_nchars(term_t t, int len, const char *s)
  921. { word str = globalNString(len, (char *)s);
  922.   Word p = valHandleP(t);
  923.  
  924.   return unifyAtomic(p, str);
  925. }
  926.  
  927. #endif
  928.  
  929.          /*******************************
  930.          *             PUT-*          *
  931.          *******************************/
  932.  
  933. void
  934. PL_put_variable(term_t t)
  935. { Word p = allocGlobal(1);
  936.  
  937.   setVar(*p);
  938.   setHandle(t, makeRef(p));
  939. }
  940.  
  941.  
  942. void
  943. PL_put_atom(term_t t, atom_t a)
  944. { setHandle(t, a);
  945. }
  946.  
  947.  
  948. void
  949. PL_put_atom_chars(term_t t, const char *s)
  950. { setHandle(t, lookupAtom(s));
  951. }
  952.  
  953.  
  954. void
  955. PL_put_string_chars(term_t t, const char *s)
  956. { word w = globalString(s);
  957.  
  958.   setHandle(t, w);
  959. }
  960.  
  961. void
  962. PL_put_list_chars(term_t t, const char *chars)
  963. { int len = strlen(chars);
  964.   
  965.   if ( len == 0 )
  966.   { setHandle(t, ATOM_nil);
  967.   } else
  968.   { Word p = allocGlobal(len*3);
  969.     setHandle(t, consPtr(p, TAG_COMPOUND|STG_GLOBAL));
  970.  
  971.     for( ; *chars ; chars++)
  972.     { *p++ = FUNCTOR_dot2;
  973.       *p++ = consInt((long)*chars & 0xff);
  974.       *p = consPtr(p+1, TAG_COMPOUND|STG_GLOBAL);
  975.       p++;
  976.     }
  977.     p[-1] = ATOM_nil;
  978.   }
  979. }
  980.  
  981. void
  982. PL_put_integer(term_t t, long i)
  983. { setHandle(t, makeNum(i));
  984. }
  985.  
  986.  
  987. void
  988. _PL_put_number(term_t t, Number n)
  989. { if ( intNumber(n) )
  990.     PL_put_integer(t, n->value.i);
  991.   else
  992.     PL_put_float(t, n->value.f);
  993. }
  994.  
  995.  
  996. void
  997. PL_put_pointer(term_t t, void *ptr)
  998. { PL_put_integer(t, pointerToLong(ptr));
  999. }
  1000.  
  1001.  
  1002. void
  1003. PL_put_float(term_t t, double f)
  1004. { setHandle(t, globalReal(f));
  1005. }
  1006.  
  1007.  
  1008. void
  1009. PL_put_functor(term_t t, functor_t f)
  1010. { int arity = arityFunctor(f);
  1011.  
  1012.   if ( arity == 0 )
  1013.   { setHandle(t, nameFunctor(f));
  1014.   } else
  1015.   { Word a = allocGlobal(1 + arity);
  1016.  
  1017.     setHandle(t, consPtr(a, TAG_COMPOUND|STG_GLOBAL));
  1018.     *a++ = f;
  1019.     while(arity-- > 0)
  1020.       setVar(*a++);
  1021.   }
  1022. }
  1023.  
  1024.  
  1025. void
  1026. PL_put_list(term_t l)
  1027. { Word a = allocGlobal(3);
  1028.  
  1029.   setHandle(l, consPtr(a, TAG_COMPOUND|STG_GLOBAL));
  1030.   *a++ = FUNCTOR_dot2;
  1031.   setVar(*a++);
  1032.   setVar(*a);
  1033. }
  1034.  
  1035.  
  1036. void
  1037. PL_put_nil(term_t l)
  1038. { setHandle(l, ATOM_nil);
  1039. }
  1040.  
  1041.  
  1042. void
  1043. PL_put_term(term_t t1, term_t t2)
  1044. { Word p2 = valHandleP(t2);
  1045.  
  1046.   deRef(p2);
  1047.   setHandle(t1, isVar(*p2) ? makeRef(p2) : *p2);
  1048. }
  1049.  
  1050.  
  1051. void
  1052. _PL_put_xpce_reference_i(term_t t, unsigned long r)
  1053. { Word a = allocGlobal(2);
  1054.  
  1055.   setHandle(t, consPtr(a, TAG_COMPOUND|STG_GLOBAL));
  1056.   *a++ = FUNCTOR_xpceref1;
  1057.   *a++ = makeNum(r);
  1058. }
  1059.  
  1060.  
  1061. void
  1062. _PL_put_xpce_reference_a(term_t t, atom_t name)
  1063. { Word a = allocGlobal(2);
  1064.  
  1065.   setHandle(t, consPtr(a, TAG_COMPOUND|STG_GLOBAL));
  1066.   *a++ = FUNCTOR_xpceref1;
  1067.   *a++ = name;
  1068. }
  1069.  
  1070.  
  1071.          /*******************************
  1072.          *           UNIFY        *
  1073.          *******************************/
  1074.  
  1075. int
  1076. PL_unify_atom(term_t t, atom_t a)
  1077. { Word p = valHandleP(t);
  1078.  
  1079.   return unifyAtomic(p, a);
  1080. }
  1081.  
  1082.  
  1083. int
  1084. PL_unify_functor(term_t t, functor_t f)
  1085. { Word p = valHandleP(t);
  1086.   int arity = arityFunctor(f);
  1087.  
  1088.   deRef(p);
  1089.   if ( isVar(*p) )
  1090.   { if ( arity == 0 )
  1091.     { *p = nameFunctor(f);
  1092.     } else
  1093.     { 
  1094. #ifdef O_SHIFT_STACKS
  1095.       if ( !roomStack(global) > (1+arity) * sizeof(word) )
  1096.       { growStacks(environment_frame, NULL, FALSE, TRUE, FALSE);
  1097.     p = valHandleP(t);
  1098.     deRef(p);
  1099.       }
  1100. #else 
  1101.       requireStack(global, sizeof(word)*(1+arity));
  1102. #endif
  1103.  
  1104.       { Word a = gTop;
  1105.     gTop += 1+arity;
  1106.  
  1107.     *p = consPtr(a, TAG_COMPOUND|STG_GLOBAL);
  1108.     *a++ = f;
  1109.     for( ; arity > 0; a++, arity-- )
  1110.       setVar(*a);
  1111.       }
  1112.     }
  1113.  
  1114.     DoTrail(p);
  1115.     succeed;
  1116.   } else
  1117.   { if ( arity == 0  )
  1118.     { if ( *p == nameFunctor(f) )
  1119.     succeed;
  1120.     } else
  1121.     { if ( hasFunctor(*p, f) )
  1122.     succeed;
  1123.     }
  1124.  
  1125.     fail;
  1126.   }
  1127. }
  1128.  
  1129.  
  1130. int
  1131. PL_unify_atom_chars(term_t t, const char *chars)
  1132. { Word p = valHandleP(t);
  1133.  
  1134.   return unifyAtomic(p, lookupAtom((char *)chars));
  1135. }
  1136.  
  1137.  
  1138. int
  1139. PL_unify_list_chars(term_t l, const char *chars)
  1140. { term_t head = PL_new_term_ref();
  1141.   term_t t    = PL_copy_term_ref(l);
  1142.   int rval;
  1143.  
  1144.   for( ; *chars; chars++ )
  1145.   { if ( !PL_unify_list(t, head, t) ||
  1146.      !PL_unify_integer(head, (int)*chars & 0xff) )
  1147.       fail;
  1148.   }
  1149.  
  1150.   rval = PL_unify_nil(t);
  1151.   PL_reset_term_refs(head);
  1152.  
  1153.   return rval;
  1154. }
  1155.  
  1156.  
  1157. int
  1158. PL_unify_integer(term_t t, long i)
  1159. { Word p = valHandleP(t);
  1160.  
  1161.   return unifyAtomic(p, makeNum(i));
  1162. }
  1163.  
  1164.  
  1165. int
  1166. _PL_unify_number(term_t t, Number n)
  1167. { if ( intNumber(n) )
  1168.     return PL_unify_integer(t, n->value.i);
  1169.   else
  1170.     return PL_unify_float(t, n->value.f);
  1171. }
  1172.  
  1173.  
  1174. int
  1175. PL_unify_pointer(term_t t, void *ptr)
  1176. { return PL_unify_integer(t, pointerToLong(ptr));
  1177. }
  1178.  
  1179.  
  1180. int
  1181. PL_unify_float(term_t t, double f)
  1182. { word w = globalReal(f);
  1183.   Word p = valHandleP(t);
  1184.  
  1185.   return unifyAtomic(p, w);
  1186. }
  1187.  
  1188.  
  1189. int
  1190. PL_unify_arg(int index, term_t t, term_t a)
  1191. { word w = valHandle(t);
  1192.  
  1193.   if ( isTerm(w) &&
  1194.        index > 0 &&
  1195.        index <= (int)arityFunctor(functorTerm(w)) )
  1196.   { Word p = argTermP(w, index-1);
  1197.     Word p2 = valHandleP(a);
  1198.  
  1199.     return unify_ptrs(p, p2);
  1200.   }
  1201.  
  1202.   fail;
  1203. }
  1204.  
  1205.  
  1206. int                    /* can be faster! */
  1207. PL_unify_list(term_t l, term_t h, term_t t)
  1208. { if ( PL_unify_functor(l, FUNCTOR_dot2) )
  1209.   { PL_get_list(l, h, t);
  1210.  
  1211.     succeed;
  1212.   }
  1213.  
  1214.   fail;
  1215. }
  1216.  
  1217.  
  1218. int
  1219. PL_unify_nil(term_t l)
  1220. { Word p = valHandleP(l);
  1221.  
  1222.   return unifyAtomic(p, ATOM_nil);
  1223. }
  1224.  
  1225. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1226. Fixed by Franklin Chen <chen@adi.com> to   compile on MkLinux, where you
  1227. cannot assign to va_list as it is an array. Thanks!
  1228. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1229.  
  1230. typedef struct va_list_rec {
  1231.   va_list v;
  1232. } va_list_rec;
  1233.  
  1234. #define args argsRec.v
  1235.  
  1236. static int
  1237. unify_termVP(term_t t, va_list_rec *argsRecP)
  1238. { va_list_rec argsRec = *argsRecP;
  1239.   int rval;
  1240.  
  1241.   switch(va_arg(args, int))
  1242.   { case PL_VARIABLE:
  1243.       rval = TRUE;
  1244.       break;
  1245.     case PL_ATOM:
  1246.       rval = PL_unify_atom(t, va_arg(args, atom_t));
  1247.       break;
  1248.     case PL_INTEGER:
  1249.       rval = PL_unify_integer(t, va_arg(args, long));
  1250.       break;
  1251.     case PL_POINTER:
  1252.       rval = PL_unify_pointer(t, va_arg(args, void *));
  1253.       break;
  1254.     case PL_FLOAT:
  1255.       rval = PL_unify_float(t, va_arg(args, double));
  1256.       break;
  1257.     case PL_STRING:
  1258.       rval = PL_unify_string_chars(t, va_arg(args, const char *));
  1259.       break;
  1260.     case PL_TERM:
  1261.       rval = PL_unify(t, va_arg(args, term_t));
  1262.       break;
  1263.     case PL_CHARS:
  1264.       rval = PL_unify_atom_chars(t, va_arg(args, const char *));
  1265.       break;
  1266.     case PL_FUNCTOR:
  1267.     { functor_t ft = va_arg(args, functor_t);
  1268.       int arity = arityFunctor(ft);
  1269.       term_t tmp = PL_new_term_ref();
  1270.       int n;
  1271.  
  1272.       if ( !PL_unify_functor(t, ft) )
  1273.     goto failout;
  1274.  
  1275.       for(n=1; n<=arity; n++)
  1276.       {    _PL_get_arg(n, t, tmp);
  1277.     
  1278.     rval = unify_termVP(tmp, &argsRec);
  1279.     if ( !rval )
  1280.       goto failout;
  1281.       }
  1282.  
  1283.       rval = TRUE;
  1284.       PL_reset_term_refs(tmp);
  1285.       break;
  1286.     failout:
  1287.       rval = FALSE;
  1288.       PL_reset_term_refs(tmp);
  1289.       break;
  1290.     }
  1291.     case PL_LIST:
  1292.     { int length = va_arg(args, int);
  1293.       term_t tmp = PL_copy_term_ref(t);
  1294.       term_t h   = PL_new_term_ref();
  1295.  
  1296.       for( ; length-- > 0; )
  1297.       { PL_unify_list(tmp, h, tmp);
  1298.     rval = unify_termVP(h, &argsRec);
  1299.     if ( !rval )
  1300.       goto listfailout;
  1301.       }
  1302.  
  1303.       rval = PL_unify_nil(tmp);
  1304.       PL_reset_term_refs(tmp);
  1305.       break;
  1306.     listfailout:
  1307.       PL_reset_term_refs(tmp);
  1308.       break;
  1309.     }
  1310.     default:
  1311.       PL_warning("Format error in PL_unify_term()");
  1312.       rval = FALSE;
  1313.   }
  1314.  
  1315.   *argsRecP = argsRec;
  1316.   return rval;
  1317. }
  1318.  
  1319. int
  1320. PL_unify_term(term_t t, ...)
  1321. {
  1322.   va_list_rec argsRec;
  1323.   int rval;
  1324.  
  1325.   va_start(args, t);
  1326.   rval = unify_termVP(t, &argsRec);
  1327.   va_end(args);
  1328.  
  1329.   return rval;
  1330. }
  1331.  
  1332. #undef args
  1333.  
  1334. int
  1335. _PL_unify_xpce_reference(term_t t, xpceref_t *ref)
  1336. { Word p = valHandleP(t);
  1337.  
  1338.   do
  1339.   { if ( isVar(*p) )
  1340.     { Word a = allocGlobal(2);
  1341.   
  1342.       *p = consPtr(a, TAG_COMPOUND|STG_GLOBAL);
  1343.       DoTrail(p);
  1344.       *a++ = FUNCTOR_xpceref1;
  1345.       if ( ref->type == PL_INTEGER )
  1346.     *a++ = makeNum(ref->value.i);
  1347.       else
  1348.     *a++ = ref->value.a;
  1349.   
  1350.       succeed;
  1351.     } 
  1352.     if ( hasFunctor(*p, FUNCTOR_xpceref1) )
  1353.     { Word a = argTermP(*p, 0);
  1354.       word v = (ref->type == PL_INTEGER ? makeNum(ref->value.i)
  1355.                     : ref->value.a);
  1356.   
  1357.       deRef(a);
  1358.       return unifyAtomic(a, v);
  1359.     }
  1360.   } while ( isRef(*p) && (p = unRef(*p)));
  1361.  
  1362.   fail;
  1363. }
  1364.  
  1365.  
  1366.          /*******************************
  1367.          *       ATOMIC (INTERNAL)    *
  1368.          *******************************/
  1369.  
  1370. atomic_t
  1371. _PL_get_atomic(term_t t)
  1372. { return valHandle(t);
  1373. }
  1374.  
  1375.  
  1376. int
  1377. _PL_unify_atomic(term_t t, atomic_t a)
  1378. { Word p = valHandleP(t);
  1379.  
  1380.   return unifyAtomic(p, a);
  1381. }
  1382.  
  1383.  
  1384. void
  1385. _PL_put_atomic(term_t t, atomic_t a)
  1386. { setHandle(t, a);
  1387. }
  1388.  
  1389.  
  1390. void
  1391. _PL_copy_atomic(term_t t, atomic_t arg) /* internal one */
  1392. { word a;
  1393.  
  1394.   if ( isIndirect(arg) )
  1395.     a = globalIndirect(arg);
  1396.   else
  1397.     a = arg;
  1398.   
  1399.   setHandle(t, a);
  1400. }
  1401.  
  1402.  
  1403.          /*******************************
  1404.          *           TYPE        *
  1405.          *******************************/
  1406.  
  1407.  
  1408. int
  1409. PL_term_type(term_t t)
  1410. { word w = valHandle(t);
  1411.  
  1412.   if ( isVar(w) )        return PL_VARIABLE;
  1413.   if ( isInteger(w) )        return PL_INTEGER;
  1414.   if ( isReal(w) )        return PL_FLOAT;
  1415. #if O_STRING
  1416.   if ( isString(w) )        return PL_STRING;
  1417. #endif /* O_STRING */
  1418.   if ( isAtom(w) )        return PL_ATOM;
  1419.  
  1420.   assert(isTerm(w));
  1421.                   return PL_TERM;
  1422. }
  1423.  
  1424.          /*******************************
  1425.          *          UNIFY        *
  1426.          *******************************/
  1427.  
  1428. int
  1429. PL_unify(term_t t1, term_t t2)
  1430. { Word p1 = valHandleP(t1);
  1431.   Word p2 = valHandleP(t2);
  1432.   mark m;
  1433.   int rval;
  1434.  
  1435.   Mark(m);
  1436.   if ( !(rval = unify(p1, p2, environment_frame)) )
  1437.     Undo(m);
  1438.  
  1439.   return rval;  
  1440. }
  1441.  
  1442.  
  1443.          /*******************************
  1444.          *           MODULES        *
  1445.          *******************************/
  1446.  
  1447. int
  1448. PL_strip_module(term_t raw, module_t *m, term_t plain)
  1449. { Word r = valHandleP(raw);
  1450.   Word p;
  1451.  
  1452.   if ( (p = stripModule(r, m)) )
  1453.   { setHandle(plain, isVar(*p) ? makeRef(p) : *p);
  1454.     succeed;
  1455.   }
  1456.  
  1457.   fail;
  1458. }
  1459.  
  1460.         /********************************
  1461.         *            MODULES            *
  1462.         *********************************/
  1463.  
  1464. module_t
  1465. PL_context()
  1466. { return environment_frame ? contextModule(environment_frame)
  1467.                : MODULE_user;
  1468. }
  1469.  
  1470. atom_t
  1471. PL_module_name(Module m)
  1472. { return (atom_t) m->name;
  1473. }
  1474.  
  1475. module_t
  1476. PL_new_module(atom_t name)
  1477. { return lookupModule(name);
  1478. }
  1479.  
  1480.  
  1481.          /*******************************
  1482.          *        PREDICATES        *
  1483.          *******************************/
  1484.  
  1485. predicate_t
  1486. PL_pred(functor_t functor, module_t module)
  1487. { if ( module == NULL )
  1488.     module = PL_context();
  1489.  
  1490.   return lookupProcedure(functor, module);
  1491. }
  1492.  
  1493.  
  1494. predicate_t
  1495. PL_predicate(const char *name, int arity, const char *module)
  1496. { Module m = module ? lookupModule(lookupAtom(module)) : PL_context();
  1497.   functor_t f = lookupFunctorDef(lookupAtom(name), arity);
  1498.  
  1499.   return PL_pred(f, m);
  1500. }
  1501.  
  1502.  
  1503. predicate_t
  1504. _PL_predicate(const char *name, int arity, const char *module,
  1505.           predicate_t *bin)
  1506. { if ( !*bin )
  1507.     *bin = PL_predicate(name, arity, module);
  1508.  
  1509.   return *bin;
  1510. }
  1511.  
  1512.  
  1513. int
  1514. PL_predicate_info(predicate_t pred, atom_t *name, int *arity, module_t *m)
  1515. { if ( pred->type == PROCEDURE_TYPE )
  1516.   { *name  = pred->definition->functor->name;
  1517.     *arity = pred->definition->functor->arity;
  1518.     *m     = pred->definition->module;
  1519.  
  1520.     succeed;
  1521.   }
  1522.  
  1523.   fail;
  1524. }
  1525.  
  1526.          /*******************************
  1527.          *           CALLING        *
  1528.          *******************************/
  1529.  
  1530. int
  1531. PL_call_predicate(Module ctx, int flags, predicate_t pred, term_t h0)
  1532. { int rval;
  1533.  
  1534.   qid_t qid = PL_open_query(ctx, flags, pred, h0);
  1535.   rval = PL_next_solution(qid);
  1536.   PL_cut_query(qid);
  1537.  
  1538.   return rval;
  1539. }
  1540.  
  1541.  
  1542. bool
  1543. PL_call(term_t t, Module m)
  1544. { return callProlog(m, t, TRUE);
  1545. }  
  1546.  
  1547.  
  1548.         /********************************
  1549.         *     FOREIGNS RETURN        *
  1550.         ********************************/
  1551.  
  1552. foreign_t
  1553. _PL_retry(long v)
  1554. { ForeignRedoInt(v);
  1555. }
  1556.  
  1557.  
  1558. foreign_t
  1559. _PL_retry_address(void *v)
  1560. { if ( (ulong)v & FRG_CONTROL_MASK )
  1561.     PL_fatal_error("PL_retry_address(0x%lx): bad alignment", (ulong)v);
  1562.  
  1563.   ForeignRedoPtr(v);
  1564. }
  1565.  
  1566.  
  1567. long
  1568. PL_foreign_context(control_t h)
  1569. { return ForeignContextInt(h);
  1570. }
  1571.  
  1572. void *
  1573. PL_foreign_context_address(control_t h)
  1574. { return ForeignContextPtr(h);
  1575. }
  1576.  
  1577.  
  1578. int
  1579. PL_foreign_control(control_t h)
  1580. { return ForeignControl(h);
  1581. }
  1582.  
  1583.  
  1584. int
  1585. PL_throw(term_t exception)
  1586. { PL_put_term(exception_bin, exception);
  1587.  
  1588.   exception_term = exception_bin;
  1589.  
  1590.   fail;
  1591. }
  1592.  
  1593.         /********************************
  1594.         *      REGISTERING FOREIGNS     *
  1595.         *********************************/
  1596.  
  1597. static void
  1598. notify_registered_foreign(functor_t fd, Module m)
  1599. { if ( GD->initialised )
  1600.   { fid_t cid = PL_open_foreign_frame();
  1601.     term_t argv = PL_new_term_refs(2);
  1602.     predicate_t pred = _PL_predicate("$foreign_registered", 2, "system",
  1603.                      &GD->procedures.foreign_registered2);
  1604.  
  1605.     PL_put_atom(argv+0, m->name);
  1606.     PL_put_functor(argv+1, fd);
  1607.     PL_call_predicate(MODULE_system, FALSE, pred, argv);
  1608.     PL_discard_foreign_frame(cid);
  1609.   }
  1610. }
  1611.  
  1612.  
  1613. bool
  1614. PL_register_foreign(const char *name, int arity, Func f, int flags)
  1615. { Procedure proc;
  1616.   Definition def;
  1617.   Module m;
  1618.   functor_t fdef = lookupFunctorDef(lookupAtom(name), arity);
  1619.  
  1620.   m = (environment_frame ? contextModule(environment_frame)
  1621.              : MODULE_system);
  1622.  
  1623.   proc = lookupProcedure(lookupFunctorDef(lookupAtom(name), arity), m);
  1624.   def = proc->definition;
  1625.  
  1626.   if ( true(def, LOCKED) )
  1627.   { warning("PL_register_foreign(): Attempt to redefine a system predicate: %s",
  1628.         procedureName(proc));
  1629.     fail;
  1630.   }
  1631.  
  1632.   if ( def->definition.function )
  1633.     warning("PL_register_foreign(): redefined %s", procedureName(proc));
  1634.   if ( false(def, FOREIGN) && def->definition.clauses != NULL )
  1635.     abolishProcedure(proc, m);
  1636.  
  1637.   def->definition.function = f;
  1638.   def->indexPattern = 0;
  1639.   def->indexCardinality = 0;
  1640.   def->flags = 0;
  1641.   set(def, FOREIGN|TRACE_ME);
  1642.   clear(def, NONDETERMINISTIC);
  1643.  
  1644.   if ( (flags & PL_FA_NOTRACE) )      clear(def, TRACE_ME);
  1645.   if ( (flags & PL_FA_TRANSPARENT) )      set(def, METAPRED);
  1646.   if ( (flags & PL_FA_NONDETERMINISTIC) ) set(def, NONDETERMINISTIC);
  1647.  
  1648.   notify_registered_foreign(fdef, m);
  1649.  
  1650.   succeed;
  1651. }  
  1652.  
  1653.  
  1654. bool
  1655. PL_load_extensions(PL_extension *ext)
  1656. { PL_extension *e;
  1657.   Module m;
  1658.  
  1659.   m = (environment_frame ? contextModule(environment_frame)
  1660.              : MODULE_system);
  1661.  
  1662.   for(e = ext; e->predicate_name; e++)
  1663.   { short flags = TRACE_ME;
  1664.     register Definition def;
  1665.     register Procedure proc;
  1666.  
  1667.     if ( e->flags & PL_FA_NOTRACE )         flags &= ~TRACE_ME;
  1668.     if ( e->flags & PL_FA_TRANSPARENT )         flags |= METAPRED;
  1669.     if ( e->flags & PL_FA_NONDETERMINISTIC ) flags |= NONDETERMINISTIC;
  1670.  
  1671.     proc = lookupProcedure(lookupFunctorDef(lookupAtom(e->predicate_name),
  1672.                         e->arity), 
  1673.                m);
  1674.     def = proc->definition;
  1675.     if ( true(def, LOCKED) )
  1676.     { warning("PL_load_extensions(): Attempt to redefine system predicate: %s",
  1677.           procedureName(proc));
  1678.       continue;
  1679.     }
  1680.     if ( def->definition.function )
  1681.       warning("PL_load_extensions(): redefined %s", procedureName(proc));
  1682.     if ( false(def, FOREIGN) && def->definition.clauses != NULL )
  1683.       abolishProcedure(proc, m);
  1684.     set(def, FOREIGN);
  1685.     set(def, flags);
  1686.     def->definition.function = e->function;
  1687.     def->indexPattern = 0;
  1688.     def->indexCardinality = 0;
  1689.  
  1690.     notify_registered_foreign(def->functor->functor, m);
  1691.   }    
  1692.  
  1693.   succeed;
  1694. }
  1695.  
  1696.          /*******************************
  1697.          *     EMBEDDING PROLOG    *
  1698.          *******************************/
  1699.  
  1700. int
  1701. PL_toplevel(void)
  1702. { return prolog(lookupAtom("$toplevel"));
  1703. }
  1704.  
  1705.  
  1706. void
  1707. PL_halt(int status)
  1708. { Halt(status);
  1709. }
  1710.  
  1711.  
  1712.         /********************************
  1713.         *            SIGNALS            *
  1714.         *********************************/
  1715.  
  1716. #if HAVE_SIGNAL
  1717. void
  1718. (*PL_signal(int sig, void (*func) (int)))(int)
  1719. { void (*old)(int);
  1720.  
  1721.   if ( sig < 1 || sig > MAXSIGNAL )
  1722.   { fatalError("PL_signal(): illegal signal number: %d", sig);
  1723.     return NULL;
  1724.   }
  1725.  
  1726.   if ( LD_sig_handler(sig).catched == FALSE )
  1727.   { old = signal(sig, func);
  1728.     LD_sig_handler(sig).os = func;
  1729.     
  1730.     return old;
  1731.   }
  1732.  
  1733.   old = LD_sig_handler(sig).user;
  1734.   LD_sig_handler(sig).user = func;
  1735.  
  1736.   return old;
  1737. }
  1738. #endif
  1739.  
  1740. void
  1741. PL_raise(int sig)
  1742. { if ( sig > 0 && sig <= MAXSIGNAL )
  1743.     signalled |= (1L << (sig-1));
  1744. }
  1745.  
  1746.  
  1747.         /********************************
  1748.         *         RESET (ABORTS)    *
  1749.         ********************************/
  1750.  
  1751. struct abort_handle
  1752. { AbortHandle      next;            /* Next handle */
  1753.   PL_abort_hook_t function;        /* The handle itself */
  1754. };
  1755.  
  1756. #define abort_head (LD->fli._abort_head)
  1757. #define abort_tail (LD->fli._abort_tail)
  1758.  
  1759. void
  1760. PL_abort_hook(PL_abort_hook_t func)
  1761. { AbortHandle h = (AbortHandle) allocHeap(sizeof(struct abort_handle));
  1762.   h->next = NULL;
  1763.   h->function = func;
  1764.  
  1765.   if ( abort_head == NULL )
  1766.   { abort_head = abort_tail = h;
  1767.   } else
  1768.   { abort_tail->next = h;
  1769.     abort_tail = h;
  1770.   }
  1771. }
  1772.  
  1773.  
  1774. int
  1775. PL_abort_unhook(PL_abort_hook_t func)
  1776. { AbortHandle h = abort_head;
  1777.  
  1778.   for(; h; h = h->next)
  1779.   { if ( h->function == func )
  1780.     { h->function = NULL;
  1781.       return TRUE;
  1782.     }
  1783.   }
  1784.  
  1785.   return FALSE;
  1786. }
  1787.  
  1788.  
  1789. void
  1790. resetForeign(void)
  1791. { AbortHandle h = abort_head;
  1792.  
  1793.   for(; h; h = h->next)
  1794.     if ( h->function )
  1795.       (*h->function)();
  1796. }
  1797.  
  1798.  
  1799.         /********************************
  1800.         *        FOREIGN INITIALISE    *
  1801.         ********************************/
  1802.  
  1803. struct initialise_handle
  1804. { InitialiseHandle      next;            /* Next handle */
  1805.   PL_initialise_hook_t function;        /* The handle itself */
  1806. };
  1807.  
  1808. #define initialise_head (LD->fli._initialise_head)
  1809. #define initialise_tail (LD->fli._initialise_tail)
  1810.  
  1811. void
  1812. PL_initialise_hook(PL_initialise_hook_t func)
  1813. { InitialiseHandle h = initialise_head;
  1814.  
  1815.   for(; h; h = h->next)
  1816.   { if ( h->function == func )
  1817.       return;                /* already there */
  1818.   }
  1819.  
  1820.   h = (InitialiseHandle) malloc(sizeof(struct initialise_handle));
  1821.  
  1822.   h->next = NULL;
  1823.   h->function = func;
  1824.  
  1825.   if ( initialise_head == NULL )
  1826.   { initialise_head = initialise_tail = h;
  1827.   } else
  1828.   { initialise_tail->next = h;
  1829.     initialise_tail = h;
  1830.   }
  1831. }
  1832.  
  1833.  
  1834. void
  1835. initialiseForeign(int argc, char **argv)
  1836. { InitialiseHandle h = initialise_head;
  1837.  
  1838.   for(; h; h = h->next)
  1839.     (*h->function)(argc, argv);
  1840. }
  1841.  
  1842.  
  1843.          /*******************************
  1844.          *          PROMPT        *
  1845.          *******************************/
  1846.  
  1847. void
  1848. PL_prompt1(const char *s)
  1849. { prompt1((char *) s);
  1850. }
  1851.  
  1852.  
  1853. int
  1854. PL_ttymode(int fd)
  1855. { if ( fd == 0 )
  1856.   { if ( GD->cmdline.notty )        /* -tty in effect */
  1857.       return PL_NOTTY;
  1858.     if ( ttymode == TTY_RAW )        /* get_single_char/1 and friends */
  1859.       return PL_RAWTTY;
  1860.     return PL_COOKEDTTY;        /* cooked (readline) input */
  1861.   } else
  1862.     return PL_NOTTY;
  1863. }
  1864.  
  1865.  
  1866. void
  1867. PL_write_prompt(int fd, int dowrite)
  1868. { if ( fd == 0 )
  1869.   { if ( dowrite )
  1870.     { extern int Output;
  1871.       int old = Output;
  1872.       Output = 1;
  1873.       Putf("%s", PrologPrompt());
  1874.       pl_flush();
  1875.       Output = old;
  1876.     }
  1877.  
  1878.     pl_ttyflush();
  1879.     GD->os.prompt_next = FALSE;
  1880.   }
  1881. }
  1882.  
  1883.  
  1884. void
  1885. PL_prompt_next(int fd)
  1886. { if ( fd == 0 )
  1887.     GD->os.prompt_next = TRUE;
  1888. }
  1889.  
  1890.  
  1891. char *
  1892. PL_prompt_string(int fd)
  1893. { if ( fd == 0 )
  1894.     return PrologPrompt();
  1895.  
  1896.   return "";
  1897. }
  1898.  
  1899.  
  1900. void
  1901. PL_add_to_protocol(const char *buf, int n)
  1902. { protocol((char *)buf, n);
  1903. }
  1904.  
  1905.  
  1906.          /*******************************
  1907.          *       DISPATCHING        *
  1908.          *******************************/
  1909.  
  1910. #define dispatch_events (LD->fli._dispatch_events)
  1911.  
  1912. PL_dispatch_hook_t
  1913. PL_dispatch_hook(PL_dispatch_hook_t hook)
  1914. { PL_dispatch_hook_t old = dispatch_events;
  1915.  
  1916.   dispatch_events = hook;
  1917.   return old;
  1918. }
  1919.  
  1920. int
  1921. PL_dispatch(int fd, int wait)
  1922. { int rval;
  1923.  
  1924.   if ( wait == PL_DISPATCH_INSTALLED )
  1925.     return dispatch_events ? TRUE : FALSE;
  1926.  
  1927.   if ( dispatch_events )
  1928.   { do
  1929.     { rval = (*dispatch_events)(fd);
  1930.     } while( wait == PL_DISPATCH_WAIT && rval == PL_DISPATCH_TIMEOUT );
  1931.   } else
  1932.     rval = PL_DISPATCH_INPUT;
  1933.  
  1934.   return rval;
  1935. }
  1936.  
  1937.  
  1938.          /*******************************
  1939.          *        FEATURES        *
  1940.          *******************************/
  1941.  
  1942. int
  1943. PL_set_feature(const char *name, int type, ...)
  1944. { va_list args;
  1945.   int rval = TRUE;
  1946.  
  1947.   va_start(args, type);
  1948.   switch(type)
  1949.   { case PL_ATOM:
  1950.     { char *v = va_arg(args, char *);
  1951.       setFeature(lookupAtom(name), FT_ATOM, lookupAtom(v));
  1952.       break;
  1953.     }
  1954.     case PL_INTEGER:
  1955.     { long v = va_arg(args, long);
  1956.       setFeature(lookupAtom(name), FT_INTEGER, v);
  1957.       break;
  1958.     }
  1959.     default:
  1960.       rval = FALSE;
  1961.   }
  1962.  
  1963.   va_end(args);
  1964.   return rval;
  1965. }
  1966.  
  1967.  
  1968.         /********************************
  1969.         *           WARNINGS            *
  1970.         *********************************/
  1971.  
  1972. bool
  1973. PL_warning(const char *fm, ...)
  1974. { va_list args;
  1975.  
  1976.   va_start(args, fm);
  1977.   vwarning(fm, args);
  1978.   va_end(args);
  1979.  
  1980.   fail;
  1981. }
  1982.  
  1983. void
  1984. PL_fatal_error(const char *fm, ...)
  1985. { va_list args;
  1986.  
  1987.   va_start(args, fm);
  1988.   vfatalError(fm, args);
  1989.   va_end(args);
  1990. }
  1991.  
  1992.  
  1993.         /********************************
  1994.         *            ACTIONS            *
  1995.         *********************************/
  1996.  
  1997. int
  1998. PL_action(int action, ...)
  1999. { int rval;
  2000.   va_list args;
  2001.  
  2002.   va_start(args, action);
  2003.  
  2004.   switch(action)
  2005.   { case PL_ACTION_TRACE:
  2006.       rval = pl_trace();
  2007.       break;
  2008.     case PL_ACTION_DEBUG:
  2009.       rval = pl_debug();
  2010.       break;
  2011.     case PL_ACTION_BACKTRACE:
  2012. #ifdef O_DEBUGGER
  2013.     { int a = va_arg(args, int);
  2014.  
  2015.       if ( gc_status.active )
  2016.       { Sfprintf(Serror,
  2017.          "\n[Cannot print stack while in %ld-th garbage collection]\n",
  2018.          gc_status.collections);
  2019.     fail;
  2020.       }
  2021.       if ( GD->bootsession || !GD->initialised )
  2022.       { Sfprintf(Serror,
  2023.          "\n[Cannot print stack while initialising]\n");
  2024.     fail;
  2025.       }
  2026.       backTrace(environment_frame, a);
  2027.       rval = TRUE;
  2028.     }
  2029. #else
  2030.       warning("No Prolog backtrace in runtime version");
  2031.       rval = FALSE;
  2032. #endif
  2033.       break;
  2034.     case PL_ACTION_BREAK:
  2035.       rval = pl_break();
  2036.       break;
  2037.     case PL_ACTION_HALT:
  2038.     { int a = va_arg(args, int);
  2039.  
  2040.       Halt(a);
  2041.       rval = FALSE;
  2042.       break;
  2043.     }
  2044.     case PL_ACTION_ABORT:
  2045.       rval = pl_abort();
  2046.       break;
  2047.     case PL_ACTION_SYMBOLFILE:
  2048.     { char *name = va_arg(args, char *);
  2049.       loaderstatus.symbolfile = lookupAtom(name);
  2050.       rval = TRUE;
  2051.       break;
  2052.     }
  2053.     case PL_ACTION_WRITE:
  2054.     { char *s = va_arg(args, char *);
  2055.       Putf("%s", (char *)s);
  2056.       rval = TRUE;
  2057.       break;
  2058.     }
  2059.     case PL_ACTION_FLUSH:
  2060.       rval = pl_flush();
  2061.       break;
  2062.     default:
  2063.       sysError("PL_action(): Illegal action: %d", action);
  2064.       /*NOTREACHED*/
  2065.       rval = FALSE;
  2066.   }
  2067.  
  2068.   va_end(args);
  2069.  
  2070.   return rval;
  2071. }
  2072.  
  2073.         /********************************
  2074.         *         QUERY PROLOG          *
  2075.         *********************************/
  2076.  
  2077. #define c_argc (GD->cmdline._c_argc)
  2078. #define c_argv (GD->cmdline._c_argv)
  2079.  
  2080. static void
  2081. init_c_args()
  2082. { if ( c_argc == -1 )
  2083.   { int i;
  2084.     int argc    = GD->cmdline.argc;
  2085.     char **argv = GD->cmdline.argv;
  2086.  
  2087.     c_argv = allocHeap(argc * sizeof(char *));
  2088.     c_argv[0] = argv[0];
  2089.     c_argc = 1;
  2090.  
  2091.     for(i=1; i<argc; i++)
  2092.     { if ( argv[i][0] == '-' )
  2093.       { switch(argv[i][1])
  2094.     { case 'x':
  2095.       case 'g':
  2096.       case 'd':
  2097.       case 'f':
  2098.       case 't':
  2099.         i++;
  2100.         continue;
  2101.       case 'B':
  2102.       case 'L':
  2103.       case 'G':
  2104.       case 'O':
  2105.       case 'T':
  2106.       case 'A':
  2107.         continue;
  2108.     }
  2109.       }
  2110.       c_argv[c_argc++] = argv[i];
  2111.     }
  2112.   }
  2113. }
  2114.  
  2115.  
  2116. long
  2117. PL_query(int query)
  2118. { switch(query)
  2119.   { case PL_QUERY_ARGC:
  2120.       init_c_args();
  2121.       return (long) c_argc;
  2122.     case PL_QUERY_ARGV:
  2123.       init_c_args();
  2124.       return (long) c_argv;
  2125.     case PL_QUERY_SYMBOLFILE:
  2126.       if ( !getSymbols() )
  2127.     return (long) NULL;
  2128.       return (long) stringAtom(loaderstatus.symbolfile);
  2129.     case PL_QUERY_ORGSYMBOLFILE:
  2130.       if ( getSymbols() == FALSE )
  2131.     return (long) NULL;
  2132.       return (long) stringAtom(loaderstatus.orgsymbolfile);
  2133.     case PL_QUERY_MAX_INTEGER:
  2134.       return PLMAXINT;
  2135.     case PL_QUERY_MIN_INTEGER:
  2136.       return PLMININT;
  2137.     case PL_QUERY_MAX_TAGGED_INT:
  2138.       return PLMAXTAGGEDINT;
  2139.     case PL_QUERY_MIN_TAGGED_INT:
  2140.       return PLMINTAGGEDINT;
  2141.     case PL_QUERY_GETC:
  2142.       PopTty(&ttytab);            /* restore terminal mode */
  2143.       return (long) Sgetchar();        /* normal reading */
  2144.     case PL_QUERY_VERSION:
  2145.       return PLVERSION;
  2146.     default:
  2147.       sysError("PL_query: Illegal query: %d", query);
  2148.       /*NOTREACHED*/
  2149.       fail;
  2150.   }
  2151. }
  2152.  
  2153.